package main

import (
	"fmt"
	"math"
)

type Shape interface { //定义一个接口，形状
	area() float64 //求面积方法
	peri() float64 //求周长方法
}

type Circle struct{ //定义一个圆形的结构体
	radius float64 //属性是半径，求面积需要半径
}
type triangle struct { //定义一个三角形的结构体
	a,b,c float64 //有三个属性，三边长a,b,c
}
//上面的接口和结构体是没关系的
// 但是下面开始实现这个接口的方法就关联上了。
//该结构体实现了上面接口中的所有方法，该结构体就是接口的实现类

type aaa struct {
	x,y float64
}
//再看一下这个aaa结构体。下面没实现该接口。
//然后main中就会报错，说这个结构体不是实现类

func (c Circle) area()  float64 { //用圆形这个结构体来实现求面积
	return c.radius*c.radius*3.14 //求面积，pi*r的平方
}
func (c Circle) peri() float64 { //圆形这个结构体又实现了求周长方法
	return 2*3.14*c.radius //周长2*pi*r
}

func (t triangle) peri() float64  { //
	return t.a+t.b+t.c
}

func (t triangle) area() float64  {
	p:=t.peri()/2
	area:=math.Sqrt(p*(p-t.a)*(p-t.b)*(p-t.c))
	return area
}

//创建测试函数，接收的参数是一个接口类型，所以只要是这个接口的实现体接受者。都可以传入进来
//就相当于c.area()
func testshape(s Shape)  {
	fmt.Println("面积是",s.area(),"周长是：",s.peri())
}

func main()  {
	//然后调用这个函数即可，就可以测试了。用这个函数可以传任何对象进来。
	/*
	比方说传进来结构体Circle圆形，带上半径值，然后这个结构体就有半径值了，
	然后就是打印输出，输出的时候，直接调用方法area()和peri，因为都是接口下的，所以直接调用即可。
	因为函数接收的是接口类型的，因为Circle和triangle是该接口的实现类，
	老师讲过，谁实现了该接口中的所有方法。就是该接口的实现类。就有权调用该接口
	*/
	t1:=triangle{3,4,5}
	fmt.Println(t1)
	testshape(t1)
	testshape(Circle{5})
	//testshape(aaa{})
}
